/*  File Name	: EngineService.cpp
 *  Author		: Pang Jiacai
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-7-2
 *  Description:
 */

#include "EngineService.h"
#include "EngineMonitor.h"

#define BUFFER_BLOCK_SIZE	1024*512//接收消息缓存区大小

EngineService::EngineService(int p)
{
	this->reset();
}

EngineService::~EngineService()
{

}

void EngineService::reset(void)
{
	this->gate_id_ = 0;
	super::reset();
}

std::string EngineService::name(void)
{
	return std::string("EngineService");
}

const int EngineService::peer_svc_id(void)
{
	return this->peer_svc_id_;
}

int EngineService::gate_id(void)
{
	return this->gate_id_;
}

void EngineService::gate_id(int gate_id)
{
	this->gate_id_ = gate_id;
}

int EngineService::open(void *p)
{
	if (this->monitor()->bind_service(this) < 0)
	{
		return -1;
	}
	if(super::open(this->reactor())!=0)
	{
		return -1;
	}

	this->peer()->enable(O_NONBLOCK);

	int buf_length = BUFFER_BLOCK_SIZE;

	this->peer()->set_sockopt(SOL_SOCKET,SO_SNDBUF,&buf_length,sizeof(int));
	this->peer()->set_sockopt(SOL_SOCKET,SO_RCVBUF,&buf_length,sizeof(int));

//	if(this->start_timer(TimeValue(0),TimeValue(2))<0)
//	{
//		return -1;
//	}

	//this->msg_block_.init(BUFFER_BLOCK_SIZE);

	LOG((DEBUG_LOG,"EngineService::open-->[%s:%d]",this->conn_addr_,this->port_));
	return 0;
}

int EngineService::handle_input(int fd )
{
	//LockGuardReturn(RT_MUTEX,rt_mutex,this->read_lock_,-1);

	if(INVALID_HANDLER != fd)
	{
		return this->recv_msg();
	}
	return -1;
}

int EngineService::handle_output(int fd)
{
	return 0;
}

int EngineService::handle_timeout(int handle)
{
	return 0;
}

int EngineService::handle_close(int  fd,ReactorMask mask)
{
	super::handle_close(fd,mask);
	return this->monitor()->handle_close(this);
}

int EngineService::send_msg(MessageBlock *mb,int len,int flag)
{
	return Service::send_msg(mb,len,flag);
}

int EngineService::recv_msg(const int limit_size)
{
	MessageBlock *mb = NULL;
	this->monitor()->msg_pool()->pop(mb);
	if (NULL == mb)
	{
		LOG((ERROR_LOG,"EngineService::recv_msg-1->pop error"));
		return -1;
	}

	int len =0;
	bool has_data = false;
	do
	{
		mb->reset();
		len = super::recv_msg(mb, mb->size());
		if (len == -1 && (errno == EWOULDBLOCK || errno==EINTR))
		{
			this->monitor()->msg_pool()->push(mb);
			break;
		}
		else if (len <= 0)
		{
			LOG((DEBUG_LOG,"EngineService::recv_msg-->recv:[%d],error:[%d:%s]",
					len,errno,strerror(errno)));
			this->monitor()->msg_pool()->push(mb);
			return -1;
		}
		//mb->wr_len(len);
		has_data = true;
		if (this->make_block(mb, len) == -1)
		{
			LOG((ERROR_LOG,"GateService::recv_msg-->make_block error"));
			return -1;
		}
	}while (len > 0);

	if(!has_data)
	{
		return 0;
	}

	int result = 0;
	do
	{
		MessageBlock *mb = NULL;
		if (this->monitor()->msg_pool()->pop(mb) != 0)
		{
			LOG((ERROR_LOG,"EngineService::recv_msg-2->pop error"));
			return -1;
		}

		*mb << this->unique_id();
		result = this->get_block(mb);
		if (result < 0)
		{
			LOG((ERROR_LOG,"EngineService::recv_msg-->get_block error[%d]",result));
			this->monitor()->msg_pool()->push(mb);
			return -1;
		}
		else if(result==0)
		{
			this->monitor()->msg_pool()->push(mb);
			return 0;
		}
		this->monitor()->request_mb_push(mb);
	} while (result == 2);
	return 0;
}
